package cn.flying.cloud.flow.service.impl;

import java.io.Serializable;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import cn.flying.cloud.base.common.utils.Ft;
import cn.flying.cloud.base.common.vo.PageRequest;
import cn.flying.cloud.base.common.vo.PageResponse;
import cn.flying.cloud.flow.bo.FwProcInstBo;
import cn.flying.cloud.flow.entity.FwProcInst;
import cn.flying.cloud.flow.mapper.FwProcInstMapper;
import cn.flying.cloud.flow.service.FwProcInstService;

/**
 * 流程实例信息表 服务实现类
 *
 * @author admin
 * @since 2024-10-28 20:09:38
 */
@Service
public class FwProcInstServiceImpl extends ServiceImpl<FwProcInstMapper, FwProcInst> implements FwProcInstService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 查询总数
     *
     * @param param
     * @return
     */
    @Override
    public long countObj(FwProcInstBo param) {
        return this.count(getLambdaQueryWrapper(param));
    }

    /**
     * 分页查询流程实例信息表数据
     *
     * @param request
     * @return
     */
    @Override
    public PageResponse<FwProcInstBo> getPageList(PageRequest<FwProcInstBo> request) {
        FwProcInstBo param = request.getParam();
        LambdaQueryWrapper<FwProcInst> wrapper = getLambdaQueryWrapper(param);
        wrapper.orderByDesc(FwProcInst::getCreatedTime);
        Page<FwProcInst> page = this.page(new Page<>(request.getPageNum(), request.getPageSize()), wrapper);
        List<FwProcInst> records = page.getRecords();
        records.forEach(inst -> {
            if (inst.getEndTime() == null) {
                inst.setDuration(Duration.between(inst.getStartTime(), LocalDateTime.now()).toMillis() + "");
            }
        });
        return new PageResponse<>(page.getTotal(), (int) page.getCurrent(), records.stream().map(FwProcInst::toBO).collect(Collectors.toList()));
    }

    /**
     * 构建查询对象
     *
     * @param param
     * @return
     */
    private LambdaQueryWrapper<FwProcInst> getLambdaQueryWrapper(FwProcInstBo param) {
        LambdaQueryWrapper<FwProcInst> wrapper = new LambdaQueryWrapper<>();
        if (param != null) {
            if (Ft.String.isNotBlank(param.getProcInstId())) {
                wrapper.eq(FwProcInst::getProcInstId, param.getProcInstId());
            }
            if (Ft.String.isNotBlank(param.getBizKey())) {
                wrapper.eq(FwProcInst::getBizKey, param.getBizKey());
            }
            if (Ft.String.isNotBlank(param.getProcDefKey())) {
                wrapper.eq(FwProcInst::getProcDefKey, param.getProcDefKey());
            }
            if (Ft.String.isNotBlank(param.getTenantId())) {
                wrapper.eq(FwProcInst::getTenantId, param.getTenantId());
            }
            if (Ft.String.isNotBlank(param.getStartUser())) {
                wrapper.eq(FwProcInst::getStartUser, param.getStartUser());
            }
        }
        return wrapper;
    }

    /**
     * 列表查询流程实例信息表数据
     *
     * @param param
     * @return
     */
    @Override
    public List<FwProcInstBo> getList(FwProcInstBo param) {
        LambdaQueryWrapper<FwProcInst> wrapper = getLambdaQueryWrapper(param);
        // wrapper TODO
        List<FwProcInst> list = this.list(wrapper);
        return list.stream().map(FwProcInst::toBO).collect(Collectors.toList());
    }

    /**
     * 查询流程实例信息表详情数据
     *
     * @param param
     * @return
     */
    @Override
    public FwProcInstBo getOneObj(FwProcInstBo param) {
        LambdaQueryWrapper<FwProcInst> wrapper = getLambdaQueryWrapper(param);
        if (wrapper.isEmptyOfWhere()) {
            return new FwProcInstBo();
        }
        return this.getOne(wrapper).toBO();
    }

    /**
     * 根据Id查询流程实例信息表详情数据
     *
     * @param id
     * @return
     */
    @Override
    public FwProcInstBo getObjById(Serializable id) {
        return this.getById(id).toBO();
    }

    /**
     * 新增流程实例信息表数据
     *
     * @param param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean createObj(FwProcInstBo param) {
        param.setTenantId(Ft.Local.TenantId());
        FwProcInst obj = new FwProcInst();
        obj.fromBO(param);
        return this.save(obj);
    }

    /**
     * 更新流程实例信息表数据
     *
     * @param param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateObj(FwProcInstBo param) {
        FwProcInst obj = new FwProcInst();
        obj.fromBO(param);
        return this.saveOrUpdate(obj);
    }

    /**
     * 删除流程实例信息表数据
     *
     * @param param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteObj(FwProcInstBo param) {
        LambdaQueryWrapper<FwProcInst> wrapper = getLambdaQueryWrapper(param);
        // wrapper TODO
        return this.remove(wrapper);
    }

    /**
     * 根据Id删除流程实例信息表数据
     *
     * @param id
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteById(Serializable id) {
        return this.removeById(id);
    }

    /**
     * 更新流程实例状态
     *
     * @param procInstId
     * @param status
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateBusinessStatus(String procInstId, String status) {
        FwProcInst inst = this.getOne(new LambdaQueryWrapper<FwProcInst>().eq(FwProcInst::getProcInstId, procInstId));
        inst.setProcStatus(status);
        return this.updateObj(inst.toBO());
    }
}
